package com.learning.spring.bean.dynamic.config;

import com.learning.spring.bean.dynamic.config.entity.User;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanFactoryPostProcessor;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
import org.springframework.beans.factory.support.DefaultListableBeanFactory;

/**
 * ClassName: BeanDynamicConfigBeanFactoryPostProcessor
 * Description: 自定义工厂后置处理器，实现动态添加Bean
 * <p>
 * 1. DefaultListableBeanFactory 实现了 ConfigurableListableBeanFactory 接口，提供了可扩展配置、循环枚举的功能，可以通过此类实现Bean动态注入
 * 2. 为了实现在容器启动阶段能动态注入自定义Bean，保证动态注入的Bean也能被AOP所增强，需要实现Bean工厂后置处理器接口 BeanFactoryPostProcessor
 * <p>
 * Date: 2018/8/16 21:37 【需求编号】
 *
 * @author Sam Sho
 * @version V1.0.0
 */
public class BeanDynamicConfigBeanFactoryPostProcessor implements BeanFactoryPostProcessor {
    @Override
    public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {

        // DefaultListableBeanFactory 实现了 ConfigurableListableBeanFactory接口
        // 提供了可扩展配置、循环枚举的功能，可以通过此类实现 Bean 的动态注入
        DefaultListableBeanFactory factory = (DefaultListableBeanFactory) beanFactory;

        // 通过 BeanDefinitionBuilder 创建 Bean 定义
        BeanDefinitionBuilder builder = BeanDefinitionBuilder.genericBeanDefinition(User.class);

        // 设置属性
        builder.addPropertyValue("name", "sam");
        builder.addPropertyValue("age", 30);

        // 注入依赖的Bean。设置属性 address，此属性引用已经定义的 Bean:addressBeanDynamicConfig
        builder.addPropertyReference("address", "addressBeanDynamicConfig");

        // 注册 Bean 定义
        factory.registerBeanDefinition("userBeanDynamicConfigProcessor", builder.getRawBeanDefinition());

        // 也直接注册一个 Bean 实例
        factory.registerSingleton("userRegisterSingleton", new User());

    }
}
